package com.nightpiter.view.drawer.dynamic;

import java.util.ArrayList;

import com.nightpiter.model.objects.Station;
import com.nightpiter.model.objects.Transfer;
import com.nightpiter.model.objects.Transition;
import com.nightpiter.model.objects.Tunnel;
import com.nightpiter.view.Calculator;
import com.nightpiter.view.Calculator.Mode;
import com.nightpiter.view.drawer.ClassicMetroDrawer;
import com.nightpiter.view.graphics.Canvas;
import com.nightpiter.view.graphics.Point;
import com.nightpiter.view.graphics.PointF;

/**
 * @author Eldar Abusalimov (eldar.abusalimov@gmail.com)
 */
public class DynamicMetroDrawer extends ClassicMetroDrawer {

	/** a structure to draw */
	private Structure structure;

	/**
	 * default constructor
	 */
	public DynamicMetroDrawer() {
	}

	@Override
	protected boolean internalPrepare() {
		Config.drawLabels = this.mode == Mode.POSITION;
		this.structure = new Structure(modelData, mode);
		return super.internalPrepare();
	}

	@Override
	public boolean update(Station station) {
		return false;
	}

	@Override
	protected void internalDrawMetro(Canvas canvas, Calculator calculator) {
		Amoeba.setup();
		Bacillus.setup();

		for (AmoebaUltimate amoeba : structure.getAmoebas()) {
			amoeba.applyCalculator(calculator);
		}

		for (BacillusUltimate bacillus : structure.getBacilli()) {
			bacillus.draw(canvas);
		}

		for (AmoebaUltimate amoeba : structure.getAmoebas()) {
			amoeba.draw(canvas);
		}
	}

	@Override
	public void selectStation(Station station, Canvas canvas,
			Calculator calculator) {
		highlightStation(station, canvas, calculator, Config.highlightColor);
	}

	@Override
	public void showWay(ArrayList<Tunnel> selectedTunnels,
			ArrayList<Transfer> selectedTransfers,
			ArrayList<Station> selectedStations, Canvas canvas,
			Calculator calculator) {
		ArrayList<Amoeba> highlightingAmoebas = new ArrayList<Amoeba>();
		for (Tunnel tunnel : selectedTunnels) {
			highLightTransition(tunnel, canvas, calculator, Config.wayColor,
					highlightingAmoebas);
		}
		for (Station station : selectedStations) {
			highlightStation(station, canvas, calculator, Config.wayColor);
		}
		for (Amoeba amoeba : highlightingAmoebas) {
			amoeba.highlight(canvas, Config.wayColor);
		}
		structure.getPrimitiveBacillusMap();
	}

	private void highLightTransition(Transition transition, Canvas canvas,
			Calculator calculator, int color,
			ArrayList<Amoeba> highlightingAmoebas) {
		PrimitiveBacillus primitiveBacillus = structure
				.getPrimitiveBacillusMap().get(transition);
		if (primitiveBacillus != null) {
			Bacillus highlightingBacillus = primitiveBacillus;
			IntermediateBacillus intermediateBacillus = primitiveBacillus.intermediateBacillus;
			while (intermediateBacillus != null) {
				if (((IntermediateAmoeba) intermediateBacillus.evenAmoeba)
						.getCurrentDistance() > Config.mergeDistance) {
					break;
				}
				highlightingBacillus = intermediateBacillus;
				intermediateBacillus = intermediateBacillus.intermediateBacillus;
			}
			highlightingBacillus.highlight(canvas, color);
			highlightingAmoebas.add(highlightingBacillus.evenAmoeba);
			highlightingAmoebas.add(highlightingBacillus.oddAmoeba);
		}

	}

	private void highlightStation(Station station, Canvas canvas,
			Calculator calculator, int color) {
		PrimitiveAmoeba primitiveAmoeba = structure.getPrimitiveAmoebasMap()
				.get(station);
		if (primitiveAmoeba != null) {
			primitiveAmoeba.amoebaUltimate.applyCalculator(calculator);
			Amoeba highlightingAmoeba = primitiveAmoeba;
			IntermediateAmoeba intermediateAmoeba = primitiveAmoeba.intermediateAmoeba;
			while (intermediateAmoeba != null) {
				if (intermediateAmoeba.getCurrentDistance() > Config.mergeDistance) {
					break;
				}
				highlightingAmoeba = intermediateAmoeba;
				intermediateAmoeba = intermediateAmoeba.intermediateAmoeba;
			}
			highlightingAmoeba.highlight(canvas, color);
		}
	}

	@Override
	public Station[] searchStation(Point point, Calculator calculator) {
		for (AmoebaUltimate amoeba : structure.getAmoebas()) {
			amoeba.applyCalculator(calculator);
		}
		structure.getDrawnAmoebas();

		final int DELTA = 7;
		float minDist = Float.POSITIVE_INFINITY;
		float dist = 0;

		PointF pointF = new PointF();
		Amoeba nearestAmoeba = null;
		for (Amoeba amoeba : structure.getDrawnAmoebas()) {
			pointF = amoeba.pointF;
			dist = pointF.distanceTo(point);
			if (dist < minDist) {
				minDist = dist;
				nearestAmoeba = amoeba;
			}
		}

		if (nearestAmoeba != null && minDist < DELTA) {
			Station[] stations = new Station[nearestAmoeba.stations.length];
			System.arraycopy(nearestAmoeba.stations, 0, stations, 0,
					nearestAmoeba.stations.length);
			return (Station[]) stations;
		}
		return new Station[0];
	}

}
